package safe;

/**
 * 可重入问题: 锁两次(死锁)
 *
 * 外层锁要执行完整个方法才能释放
 * 内层锁要外层锁释放了才能加锁成功
 *
 * 但是synchronized实现了可重入锁
 * 可重入锁记录了当前锁被哪个线程占用着,并记录一次加锁次数
 * 外层加锁次数加1, 内层加锁次数再加1(但内层的次数不影响)
 * 之后解锁次数会减1
 *
 * 可重入锁提高了开发效率,但是降低了运行效率
 */

public class Demo4 {
    synchronized public void func(){
        synchronized (this){

        }
    }
}
/**
 * 死锁四个必要条件:
 * 1. 互斥使用, 一个锁被一个线程占用, 其他占不了
 * 2. 不可抢占, 一个锁被一个线程占用, 其他不能抢走
 * 3. 请求和保持, 当一个线程占据多个锁, 除非显式的释放锁,否则这些锁都是该线程的
 * 4. 环路等待, 等待关系也有可能成环, A等B, B等C, C等A
 *
 * 前三个都是锁自身特点
 * 第四个如何避免? 约定好多把锁加锁时
 */
